﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;

namespace CopySniffer.Common
{
    public static class ObjectLoader
    {
        public static IEnumerable<TBaseType> LoadObjects<TBaseType>(
            IEnumerable<string> assemblyNames,
            Func<Type, TBaseType> factoryMethod)
        {
            Guard.IsNotNull(assemblyNames, "assemblyNames");
            Guard.IsNotNull(factoryMethod, "factoryMethod");

            // REVIEW: would non-generic overloads be necessary too?
            Type baseType = typeof(TBaseType);

            var q = from name in assemblyNames
                    where File.Exists(name)
                    from t in Assembly.LoadFrom(name).GetTypes()
                    where baseType.IsAssignableFrom(t)
                    && ! t.IsAbstract
                    && ! t.IsInterface
                    select factoryMethod(t);

            return q;
        }

        public static IEnumerable<TBaseType> LoadObjects<TBaseType>(
            IEnumerable<string> assemblyNames)
        {
            return LoadObjects<TBaseType>(assemblyNames, (t) => (TBaseType)Activator.CreateInstance(t));
        }

        private static IEnumerable<string> GetAssemblyNames()
        {
            string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            return Directory.GetFiles(path, "CopySniffer.*.dll");
        }

        public static IEnumerable<TBaseType> LoadObjects<TBaseType>()
        {
            return LoadObjects<TBaseType>(GetAssemblyNames(), (t) => (TBaseType)Activator.CreateInstance(t));
        }
    }
}
